Go Programming - Basics
Concepts of Programming Languages
Sebastian Macke, Stefan Langer
Rosenheim Technical University
Sebastian Macke, Stefan Langer
Rosenheim Technical University
// Ints are allowed to return int returnint() { return 1; } // Structs are allowed to return typedef struct{} structdef; structdef returnstruct() { structdef mystruct; return mystruct; } // Arrays are not allowed to return int[3] returnarray() { static int myarray[3] = {1, 2, 3}; return myarray; }
-- Go doesn't allow this operation.
-- In Go, there is only one loop: for
int x; // x is a value MyClass y; // y is a reference
-- Go has pointers and values. But the way they are stored is the same.
6go env Print Go environment information
go run file.go just runs the code. Can be multiple files, too.
go build downloads dependencies and builds the executable, but needs a go.mod file.
go tool dist list list all supported platforms
env GOOS=darwin GOARCH=arm64 go build Build for Apple ARM CPU computers.
go fmt formats your files
go mod init creates a go.mod module file
go mod tidy updates the go mod file if you add more dependencies
9package main import ( "fmt" ) func main() { fmt.Printf("Hello %s", "Programming with Go \xE2\x98\xAF\n") // \xE2\x98\xAF -> ☯ fmt.Printf("Hello %s", "Programming with Go ☯\n") }
Golang | Java | Comment |
---|---|---|
bool | boolean | |
string | String | |
int | machine-sized in Go | |
int8 | byte | |
int16 | short | |
int32 | int | |
int64 | long | |
uint | - | unsigned int |
uint8 | - | |
uint16 | - | |
uint32 | - | |
uint64 | - | |
uintptr | - | |
byte | - | alias for uint8 |
rune | char | alias for int32, represents a Unicode code point. In Java usually 2 bytes. |
float32 | float | |
float64 | double | |
complex64 // complex | ||
complex128 | ||
struct {x,z,y int} | class |
package main import ( "fmt" "math/cmplx" ) func main() { c := 3 + 4i fmt.Printf("c=%v\n", c) r, θ := cmplx.Polar(c) // Go supports variables with unicode characters fmt.Printf("r=%v, θ=%v\n", r, θ) }
Languages differ of how serious they handle the type
Go uses a strong typing system. But why?
14int main() { signed int a = -1; unsigned int b = 0; if (a < b) { printf("a ís smaller than b\n"); } return 0; }
package main import "fmt" func main() { var a int32 = -1 var b uint32 = 2 if a < int32(b) { fmt.Printf("a is smaller than b") } }
func PrintVariableDetails(v any) { typeof := reflect.TypeOf(v) fmt.Printf("The variable with type '%s' has the value '%v'\n", typeof.Name(), v) } func main() { var someValue any someValue = 2 PrintVariableDetails(someValue) someValue = "abcd" PrintVariableDetails(someValue) if tmp, ok := someValue.(string); ok { fmt.Println("someValue is a string and has the value", tmp) } }
func countWords(input string) map[string]int { // Split the string into words using whitespace as a delimiter words := strings.Fields(input) // Initialize an empty map to store word counts wordCounts := make(map[string]int) // Iterate over the words and update the count in the map for _, word := range words { word = strings.ToLower(word) // Convert word to lowercase to ensure case-insensitivity wordCounts[word]++ // Increment the count for this word } return wordCounts }
append()
)arr := [5]int{1, 2, 3, 4, 5} s := arr[0:2] fmt.Println(len(s), cap(s)) // ==> 2, 5 s = append(s, 8) s = append(s, 9) s = append(s, 10) s = append(s, 11) fmt.Println(len(s), cap(s)) // ==> 6, 10
// IsPalindrome implementation. Does only work for 1-Byte UTF-8 chars (ASCII). func IsPalindrome(word string) bool { for pos := 0; pos < len(word)/2; pos++ { if word[pos] != word[len(word)-pos-1] { return false } } return true }
// palindrome_test.go func TestPalindrome(t *testing.T) { if !IsPalindrome("") { t.Error("isPalindrome('' should be true. But is false.") } if !IsPalindrome("o") { t.Error("isPalindrome('o' should be true. But is false.") } if !IsPalindrome("oto") { t.Error("isPalindrome('oto' should be true. But is false.") } if IsPalindrome("ottos") { t.Error("isPalindrome('ottos' should be false. But is true.") } }
// IsPalindrome2 is using runes. This works for all UTF-8 chars (SBC, MBC). func IsPalindrome2(word string) bool { var runes = []rune(word) for pos, ch := range runes { if ch != runes[len(runes)-pos-1] { return false } } return true }
[]rune(string)
converts a string into a slice of runespos, ch := range runes
// IsPalindrome3 is implemented by reusing Reverse(). Reverse works for UTF-8 chars. func IsPalindrome3(word string) bool { return strings.Reverse(word) == word }
A pointer is a variable which contains a memory address
func main() { var num int = 42 ptr := &num fmt.Println("Value of num:", num) // Expected Output: Value of num: 42 fmt.Println("Address of num:", &num) // Expected Output: Address of num: 0xSOME_MEMORY_ADDRESS (this will vary every run) fmt.Println("Value via pointer:", *ptr) // Expected Output: Value via pointer: 42 fmt.Println("Address stored in ptr:", ptr) // Expected Output: Address stored in ptr: 0xSOME_MEMORY_ADDRESS (same as address of num) }
func swap0(x, y int) (int, int) { return y, x }
func swap1(x, y int) { x, y = y, x }
func swap2(x *int, y *int) { *x, *y = *y, *x }
func swap3(x **int, y **int) { *x, *y = *y, *x }
func main() { var a, b = 1, 2 fmt.Printf("Initial : a=%d, b=%d\n", a, b) a, b = b, a fmt.Printf("After a,b = b,a : a=%d, b=%d\n", a, b) swap0(a, b) fmt.Printf("After swap0(a,b) : a=%d, b=%d\n", a, b) a, b = swap0(a, b) fmt.Printf("After a,b = swap0(a,b) : a=%d, b=%d\n", a, b) swap1(a, b) fmt.Printf("After swap1(a,b) : a=%d, b=%d\n", a, b) swap2(&a, &b) fmt.Printf("After swap2(&a,&b) : a=%d, b=%d\n", a, b) pa, pb := &a, &b swap3(&pa, &pb) fmt.Printf("After swap3(&pa, &pb): a=%d, b=%d, *pa=%v, *pb=%v\n", a, b, *pa, *pb) }
github.com/s-macke/concepts-of-programming-languages/blob/master/docs/exercises/Exercise2.1.md
31// Page contains an array of words. type Page []string // Book is an array of pages. type Book []Page // Index contains a list of pages for each word in a book. type Index map[string][]int // MakeIndex generates an index structure func MakeIndex(book Book) Index { idx := make(Index) for i, page := range book { for _, word := range page { pages := idx[word] idx[word] = append(pages, i) } } return idx }
package main import "fmt" type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("%v (%v years)", p.Name, p.Age) } func main() { person := Person{"Alice", 30} fmt.Println(person) }
import ( "flag" "fmt" ) // Simple test for the Go flag API. func main() { // construct a string flag with a default ip address and a description. ip := flag.String("ip", "192.168.1.1", "Overrides the default IP address.") port := flag.String("port", "8080", "Overrides the default listen port.") flag.Parse() fmt.Println("\nDefault value for IP: " + *ip) fmt.Println("\nDefault value for port: " + *port) }
github.com/s-macke/concepts-of-programming-languages/blob/master/docs/exercises/Exercise2.2.md
36